// server

// 解析管理员注册json包
void extractCalculateFromJson(cJSON *json, struct manager *man)
{
    cJSON *node = NULL;

    node = cJSON_GetObjectItem(json, "type");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find type\n");
        exit(-1);
    }
    strcpy(man->type, node->valuestring);

    node = cJSON_GetObjectItem(json, "directives");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find type\n");
        exit(-1);
    }
    strcpy(man->directives, node->valuestring);

    node = cJSON_GetObjectItem(json, "id");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find id\n");
        exit(-1);
    }
    strcpy(man->id, node->valuestring);

    node = cJSON_GetObjectItem(json, "name");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find name\n");
        exit(-1);
    }
    strcpy(man->name = node->valuestring);

    node = cJSON_GetObjectItem(json, "password1");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find password\n");
        exit(-1);
    }
    strcpy(man->password, node->valuestring);

    node = cJSON_GetObjectItem(json, "password2");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find password\n");
        exit(-1);
    }
    strcpy(man->password, node->valuestring);

    node = cJSON_GetObjectItem(json, "number");
    if (node == NULL || node->type != cJSON_Number)
    {
        printf("can't find number\n");
        exit(-1);
    }
    man->number = node->valueint;
}

// 管理员注册
int Administrator_registration(struct manager man)
{
    if (strcmp(man.type, "register") == 0)
    {

        // 初始化连接
        MYSQL *conn = mysql_init(NULL);

        if (mysql_real_connect(conn, "localhost", "root", "1", "water_pump_house", 0, NULL, 0) == NULL)
        {
            printf("%s\n", mysql_error(conn));
            mysql_close(conn);
            exit(-1);
        }

        // 查询是否存在指定 ID 和手机号的管理员记录
        char sql[128];
        sprintf(sql, "select * from Administrator where id='%s' and phone='%d'", man.id, man.phone);
        if (mysql_query(conn, sql) != 0)
        {
            printf("%s\n", mysql_error(conn));
            mysql_close(conn);
            exit(-1);
        }

        MYSQL_RES *result = mysql_use_result(conn);

        if ((MYSQL_ROW row = mysql_fetch_row(res)) != NULL)
        {
            printf("注册失败，已有该管理员信息。\n");
        }
        else if (strcmp(password1, password2) != 0)
        {
            // 如果不存在记录，比较密码，创建新记录
            char insertQuery[128];
            sprintf(insertQuery, "insert into Administrator (id,name,phone,password) values ('%s', '%s',''%d', '%s')", man.id, man.name, man.phone, man.password1);
            if (mysql_query(conn, insertQuery) != 0)
            {
                printf("%s\n", mysql_error(conn));
                mysql_close(conn);
                exit(-1);
            }
            printf("注册管理员信息成功。\n");
        }

        // 释放结果集和关闭连接
        mysql_free_result(result);
        mysql_close(conn);

        return 0;
    }
}

// 管理员登录
int Administrator_login(struct manager man)
{
    MYSQL *mysql = mysql_init(NULL);

    MYSQL *res = mysql_real_connect(mysql, "localhost", "root", "1", "water_pump_house", 0, NULL, 0);
    if (res == NULL)
    {
        printf("%s\n", mysql_error(mysql));
        mysql_close(mysql);
        exit(-1);
    }

    char sql[100];
    sprintf(sql, "select * from Administrator where id='%s' and name='%s' and password='%s'", man.id, man.name, man.password);

    int ret = mysql_query(mysql, sql);
    if (ret != 0)
    {
        printf("%s\n", mysql_error(mysql));
        mysql_close(mysql);
        exit(-1);
    }

    MYSQL_RES *result = mysql_use_result(mysql);
    MYSQL_ROW row = mysql_fetch_row(result);
    if (row != NULL)
    {
        printf("登录成功!\n");
    }
    else
    {
        printf("登录失败，输入信息有误！\n");
    }
    mysql_free_result(result);
    mysql_close(mysql);
}

void processAdminRequest(json_object *request, int clientSocket)
{
    const char *action = json_object_get_string(json_object_object_get(request, "action"));
    // 获取 JSON 对象中 "action" 字段的值，并转换为字符串
    json_object *response = json_object_new_object();
    // 创建新的 JSON 对象用于响应

    if (strcmp(action, "register") == 0)
    {
        // 如果动作是 "register"（注册）
        // Implement admin registration logic
        // 实现管理员注册逻辑
        json_object_object_add(response, "status", json_object_new_string("success"));
        // 添加响应状态为 "success"（成功）
    }
    else if (strcmp(action, "login") == 0)
    {
        // 如果动作是 "login"（登录）
        // Implement admin login logic
        // 实现管理员登录逻辑
        json_object_object_add(response, "status", json_object_new_string("success"));
        // 添加响应状态为 "success"（成功）
    }
    else if (strcmp(action, "changePassword") == 0)
    {
        // 如果动作是 "changePassword"（修改密码）
        // Implement admin password change logic
        // 实现管理员密码修改逻辑
        json_object_object_add(response, "status", json_object_new_string("success"));
        // 添加响应状态为 "success"（成功）
    }
    /*
    else if (strcmp(action, "addDevice") == 0)
    {
        // 如果动作是 "addDevice"（添加设备）
        // Implement adding monitoring device logic
        // 实现添加监控设备逻辑
        json_object_object_add(response, "status", json_object_new_string("success"));
        // 添加响应状态为 "success"（成功）
    }
    else if (strcmp(action, "deleteDevice") == 0)
    {
        // 如果动作是 "deleteDevice"（删除设备）
        // Implement deleting monitoring device logic
        // 实现删除监控设备逻辑
        json_object_object_add(response, "status", json_object_new_string("success"));
        // 添加响应状态为 "success"（成功）
    }
    else if (strcmp(action, "addEmployee") == 0)
    {
        // 如果动作是 "addEmployee"（添加员工）
        // Implement adding employee logic
        // 实现添加员工逻辑
        json_object_object_add(response, "status", json_object_new_string("success"));
        // 添加响应状态为 "success"（成功）
    }
    else if (strcmp(action, "deleteEmployee") == 0)
    {
        // 如果动作是 "deleteEmployee"（删除员工）
        // Implement deleting employee logic
        // 实现删除员工逻辑
        json_object_object_add(response, "status", json_object_new_string("success"));
        // 添加响应状态为 "success"（成功）
    }*/
    else
    {
        json_object_object_add(response, "status", json_object_new_string("error"));
        // 如果动作不匹配上述任何一种，设置响应状态为 "error"（错误）
        json_object_object_add(response, "message", json_object_new_string("Invalid admin action"));
        // 添加错误信息说明动作无效
    }

    sendResponse(clientSocket, response);
    // 发送响应给客户端
    json_object_put(response);
    // 释放响应 JSON 对象内存
}

Employee login()
{
    MYSQL *mysql = mysql_init(NULL);

    MYSQL *res = mysql_real_connect(mysql, "localhost", "root", "1", "stu", 0, NULL, 0);
    if (res == NULL)
    {
        printf("%s\n", mysql_error(mysql));
        mysql_close(mysql);
        exit(-1);
    }

    char sql[100];
    sprintf(sql, "select * from register where username='%s' and password='%s'", username, password);

    int ret = mysql_query(mysql, sql);
    if (ret != 0)
    {
        printf("%s\n", mysql_error(mysql));
        mysql_close(mysql);
        exit(-1);
    }

    MYSQL_RES *result = mysql_use_result(mysql);
    MYSQL_ROW row = mysql_fetch_row(result);
    if (row != NULL)
    {
        printf("login successfully!\n");
    }
    else
    {
        printf("Account password error!\n");
    }
    mysql_free_result(result);
    mysql_close(mysql);
}

void processEmployeeRequest(json_object *request, int clientSocket)
{
    const char *action = json_object_get_string(json_object_object_get(request, "action"));
    // 获取 JSON 对象中 "action" 字段的值，并转换为字符串
    json_object *response = json_object_new_object();
    // 创建新的 JSON 对象用于响应

    if (strcmp(action, "login") == 0)
    {
        // 如果动作是 "login"（登录）
        // Implement employee login logic
        // 实现员工登录逻辑
        json_object_object_add(response, "status", json_object_new_string("success"));
        // 添加响应状态为 "success"（成功）
    }
    else
    {
        json_object_object_add(response, "status", json_object_new_string("error"));
        // 如果动作不匹配登录，设置响应状态为 "error"（错误）
        json_object_object_add(response, "message", json_object_new_string("Invalid employee action"));
        // 添加错误信息说明动作无效
    }

    sendResponse(clientSocket, response);
    // 发送响应给客户端
    json_object_put(response);
    // 释放响应 JSON 对象内存
}

void sendResponse(int clientSocket, json_object *response)
{
    const char *responseStr = json_object_to_json_string(response);
    // 将 JSON 对象转换为字符串
    send(clientSocket, responseStr, strlen(responseStr), 0);
    // 将响应字符串发送给客户端
}

//
cJSON *createJsonWithResult(struct manager man)
{
    cJSON *responseJson = cJSON_CreateObject();
    cJSON_AddItemToObject(responseJson, "res", cJSON_CreateNumber(cal.res));
    return responseJson;
}

// 解析用户客户端登录
void users_login()
{
    node = cJSON_GetObjectItem(json, "directives");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find type\n");
        exit(-1);
    }
    strcpy(man->directives, node->valuestring);

    node = cJSON_GetObjectItem(json, "id");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find id\n");
        exit(-1);
    }
    strcpy(man->id, node->valuestring);

    node = cJSON_GetObjectItem(json, "name");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find name\n");
        exit(-1);
    }
    strcpy(man->name = node->valuestring);

    node = cJSON_GetObjectItem(json, "password");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find password\n");
        exit(-1);
    }
    strcpy(man->password, node->valuestring);
}

void processEmployeeRequest(json_object *request, int clientSocket)
{
    const char *action = json_object_get_string(json_object_object_get(request, "action"));
    // 获取 JSON 对象中 "action" 字段的值，并转换为字符串
    json_object *response = json_object_new_object();
    // 创建新的 JSON 对象用于响应

    if (strcmp(action, "login") == 0)
    {
        // 如果动作是 "login"（登录）
        // Implement employee login logic
        // 实现员工登录逻辑
        json_object_object_add(response, "status", json_object_new_string("success"));
        // 添加响应状态为 "success"（成功）
    }
    else
    {
        json_object_object_add(response, "status", json_object_new_string("error"));
        // 如果动作不匹配登录，设置响应状态为 "error"（错误）
        json_object_object_add(response, "message", json_object_new_string("Invalid employee action"));
        // 添加错误信息说明动作无效
    }

    sendResponse(clientSocket, response);
    // 发送响应给客户端
    json_object_put(response);
    // 释放响应 JSON 对象内存
}

// 监测数据解析
void Monitoring_data_processing(cJSON *json, )
{
    cJSON *node = NULL;

    node = cJSON_GetObjectItem(json, "type");
    if (node == NULL || node->type != cJSON_String)
    {
        printf("can't find type\n");
        exit(-1);
    }
}

// 处理设备数据
AlarmMessage processDeviceData(cJSON *json, int clientSocket)
{
    struct device_function alarm;
    memset(alarm.message, 0, sizeof(alarm.message));

    cJSON *root = cJSON_Parse(json);
    if (!root)
    {
        sprintf(alarm.message, "Invalid JSON data.");
        return alarm;
    }

    // 解析 JSON 数据
    cJSON *timeNode = cJSON_GetObjectItem(root, "time");
    cJSON *flowNode = cJSON_GetObjectItem(root, "flow");
    cJSON *motorTemperatureNode = cJSON_GetObjectItem(root, "motorTemperature");
    cJSON *valveStatusNode = cJSON_GetObjectItem(root, "valveStatus");
    cJSON *waterLevelNode = cJSON_GetObjectItem(root, "waterLevel");

    if (!timeNode || !flowNode || !motorTemperatureNode || !valveStatusNode || !waterLevelNode)
    {
        sprintf(alarm.message, "Missing fields in JSON data.");
        cJSON_Delete(root);
        return alarm;
    }

    int flow = flowNode->valueint;
    int motorTemperature = motorTemperatureNode->valueint;
    int valveStatus = valveStatusNode->valueint;
    int waterLevel = waterLevelNode->valueint;

    // 与标准值比较并生成报警信息
    if (flow < MIN_FLOW || flow > MAX_FLOW)
    {
        sprintf(alarm.message, "Flow exceeds standard. Current flow: %d.", flow);
    }
    else if (motorTemperature > MAX_MOTOR_TEMPERATURE)
    {
        sprintf(alarm.message, "Motor temperature exceeds standard. Current temperature: %d.", motorTemperature);
    }
    else if (waterLevel < MIN_WATER_LEVEL || waterLevel > MAX_WATER_LEVEL)
    {
        sprintf(alarm.message, "Water level exceeds standard. Current level: %d.", waterLevel);
    }
    else
    {
        sprintf(alarm.message, "Data within standard.");
    }

    cJSON_Delete(root);

    // 如果有报警信息，发送到客户端
    if (strlen(alarm.message) > 0)
    {
        send(clientSocket, alarm.message, strlen(alarm.message), 0);
    }

    return alarm;
}

// 处理客户端请求
void *handleClient(void *arg)
{
    TPOOL *pool = (TPOOL *)arg;
    int clientSocket;

    while (1)
    {
        sem_wait(&pool->semr);
        pthread_mutex_lock(&pool->mutex);
        clientSocket = front(pool->que);
        pop(pool->que);
        pthread_mutex_unlock(&pool->mutex);

        if (clientSocket == -1)
        {
            break;
        }

        char buf[1024] = {0};
        int ret;

        while (1)
        {
            ret = recv(clientSocket, buf, sizeof(buf), 0);
            if (ret == -1)
            {
                perror("recv error");
                exit(-1);
            }
            else if (ret == 0)
            {
                break;
            }

            cJSON *requestJson = cJSON_Parse(buf);

            struct manager man;
            memset(&cal, 0, sizeof(cal));

            extractCalculateFromJson(requestJson, &cal);

            if (strcmp(cal.mean, "Add") == 0)
            {
                cal.res = cal.data1 + cal.data2;
                strcpy(cal.mean, "+");
            }
            else if (strcmp(cal.mean, "Sub") == 0)
            {
                cal.res = cal.data1 - cal.data2;
                strcpy(cal.mean, "-");
            }
            else if (strcmp(cal.mean, "Mul") == 0)
            {
                cal.res = cal.data1 * cal.data2;
                strcpy(cal.mean, "*");
            }
            else if (strcmp(cal.mean, "Div") == 0)
            {
                if (cal.data2 == 0 || cal.data1 == 0)
                {
                    strcpy(cal.mean, "/");
                    printf("Error: Division by zero.\n");
                    cal.res = -1;
                }
                else
                {
                    cal.res = cal.data1 / cal.data2;
                    strcpy(cal.mean, "/");
                }
            }
            else
            {
                strcpy(cal.mean, "unknow");
                cal.res = -1;
            }

            printf("Server - Type: %d, Data1: %d, Data2: %d, Mean: %s, Res: %.2f\n", cal.type, cal.data1, cal.data2, cal.mean, cal.res);

            cJSON *responseJson = createJsonWithResult(cal);

            char *s = cJSON_Print(responseJson);

            ret = send(clientSocket, s, strlen(s), 0);
            if (ret == -1)
            {
                perror("send error");
                break;
            }

            cJSON_Delete(requestJson);
            cJSON_Delete(responseJson);
        }

        close(clientSocket);
    }

    pthread_exit(NULL);
}

void *producer(void *arg)
{
    TPOOL *pool = (TPOOL *)arg;
    int clientSocket;
    int ret;

    while (1)
    {
        clientSocket = accept(pool->sock, NULL, NULL);
        if (clientSocket == -1)
        {
            perror("accept error");
            continue;
        }

        sem_wait(&pool->semw);
        pthread_mutex_lock(&pool->mutex);
        push(pool->que, clientSocket);
        pthread_mutex_unlock(&pool->mutex);
        sem_post(&pool->semr);
    }

    pthread_exit(NULL);
}

int create_sockfd()
{
    int sockfd = 0;
    int ret;

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        perror("socket error");
        exit(-1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(5238);
    addr.sin_addr.s_addr = inet_addr("192.168.0.136");

    ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    if (ret == -1)
    {
        perror("bind error");
        exit(-1);
    }

    ret = listen(sockfd, 5);
    if (ret == -1)
    {
        perror("listen error");
        exit(-1);
    }
}

int main()
{
    log_init();
    int sockfd = create_sockfd();

    TPOOL *pool = create_threadpool(5, 10, handleClient, sockfd);

    struct exam obj;
    memset(&obj, 0, sizeof(obj));

    obj.pool = pool;
    obj.sockfd = sockfd;

    pthread_t producer_tid;
    ret = pthread_create(&producer_tid, NULL, producer, &obj);
    if (ret != 0)
    {
        perror("pthread_create producer");
        exit(-1);
    }

    pthread_join(producer_tid, NULL);

    destroy_threadpool(pool);
    close(sockfd);

    return 0;
}